package org.standard.commons.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileUploadException;
import org.standard.base.model.BaseUser;
import org.standard.commons.model.Annex;
import org.standard.commons.service.Service;
import org.standard.commons.utils.Constants;
import org.standard.commons.utils.DAO;
import org.standard.commons.utils.FlipPageInfo;
import org.standard.commons.utils.Utils;

public class ServiceImpl implements Service {

	private DAO dao;
	public void setDao(DAO dao){
		this.dao=dao;
	}
	public DAO getDao(){
		return dao;
	}
	public Object findPOJOById(Class classPOJO, String id){
		
		return dao.find(classPOJO, id);
	}
	public void createPOJO(Object beo) {
		
		dao.save(beo);
	}
	public void modifyPOJO(Object beo) {
		
		dao.update(beo);
	}
	public void deletePOJO(Object beo) {
		
		dao.delete(beo);
	}
	public void deletePOJO(Class classPOJO, String id){
		
		dao.delete(classPOJO, id);
	}
	public void deleteCascadePOJO(Class classParent, String[][] classChild, String id) throws SQLException {
		if(classChild == null){
			dao.delete(classParent, id);
			return;
		}
		for(int i = 0; i < classChild.length; i++){
			dao.delOrUpdate("delete from "+classChild[i][0]+" where "+classChild[i][1]+" = '"+id+"'");
		}
		dao.delete(classParent, id);
	}
	public FlipPageInfo findPOJOList(Class classPOJO, FlipPageInfo flipPageInfo) {
		
		return findPOJOList(classPOJO,
				flipPageInfo, null, null);
	}
	public FlipPageInfo findPOJOList(Class classPOJO,
			FlipPageInfo flipPageInfo, String[][] search) {
		
		return findPOJOList(classPOJO,
				flipPageInfo, search, null);
	}
	public FlipPageInfo findPOJOList(Class classPOJO,
			FlipPageInfo flipPageInfo, String[][] search, String[][] sort) {
		
		StringBuffer sql = new StringBuffer();
		sql.append("from ").append(classPOJO.getName()).append(" where 1=1 ");
		if(search == null){
			return dao.findWithPaging(sql.toString(), flipPageInfo);
		}
		for(int i = 0; i < search.length; i++){
			String current[] = search[i];
			if(!Utils.isStringNull(current[1])){
				sql.append(" and " + current[0] + " like '%" + current[1] + "%'");
			}
		}
		if(sort == null){
			return dao.findWithPaging(sql.toString(), flipPageInfo);
		}
		sql.append(" order by ");
		for(int i = 0; i < sort.length; i++){
			String current[] = sort[i];
			if(current[1].equals("0")){
				sql.append(current[0] + " asc");
			}else{
				sql.append(current[0] + " desc");
			}
		}
		return dao.findWithPaging(sql.toString(), flipPageInfo);
	}
	public FlipPageInfo findPOJOList(String sql, FlipPageInfo flipPageInfo) {
		
		return dao.findWithPaging(sql, flipPageInfo);
	}
	@Override
	public List findPOJOList(Class classPOJO, String[] select, String[][] search, String[] groupBy){
		StringBuffer sql = new StringBuffer();
		if(select != null){
			sql.append("select ");
			for(int i = 0; i < select.length; i++){
				sql.append(select[i]);
				if(i != select.length-1){
					sql.append(" , ");
				}
			}
		}
		sql.append(" from ").append(classPOJO.getName()).append(" where 1=1 ");;
		if(search != null){
			for(int i = 0; i < search.length; i++){
				String current[] = search[i];
				if(!Utils.isStringNull(current[1])){
					sql.append(" and " + current[0] + " = '" + current[1] + "'");
				}
			}
		}
		if(groupBy != null){
			sql.append(" group by ");
			for(int i = 0; i < groupBy.length; i++){
				sql.append(groupBy[i]);
				if(i != groupBy.length-1){
					sql.append(" , ");
				}
			}
		}
		return dao.find(sql.toString());
	}
	public List findPOJOList(String sql) {
		return dao.find(sql);
	}
	@Override
	public FlipPageInfo findPOJOList(String[] select, Class[] classPOJO,
			FlipPageInfo flipPageInfo, String[][] search, String[][] sort) {
		StringBuffer sql = new StringBuffer();
		if(select != null){
			sql.append("select ");
			for (int i = 0; i < select.length; i++) {
				sql.append(select[i]);
				if (i != select.length - 1) {
					sql.append(",");
				}
			}
		}
		sql.append(" from ");
		for (int i = 0; i < classPOJO.length; i++) {
			sql.append(classPOJO[i].getName() + classPOJO[i].getName());
			if (i != classPOJO.length - 1) {
				sql.append(",");
			}
		}
		sql.append(" where 1=1 ");
		if(search == null){
			return dao.findWithPaging(sql.toString(), flipPageInfo);
		}
		for(int i = 0; i < search.length; i++){
			String current[] = search[i];
			if(!Utils.isStringNull(current[1])){
				sql.append(" and " + current[0] + " like '%" + current[1] + "%'");
			}
		}
		if(sort == null){
			return dao.findWithPaging(sql.toString(), flipPageInfo);
		}
		sql.append(" order by ");
		for(int i = 0; i < sort.length; i++){
			String current[] = search[i];
			if(current[1].equals("0")){
				sql.append(current[0] + " asc");
			}else{
				sql.append(current[0] + " desc");
			}
		}
		return dao.findWithPaging(sql.toString(), flipPageInfo);
	}
	public void modifyMergePOJO(Object beo) {
		dao.updateMerge(beo);
	}
	public FlipPageInfo findWithPagingBySql(String sql, FlipPageInfo flipPageInfo) {
		return dao.findWithPagingBySql(sql, flipPageInfo);
	}
	@Override
	public List findPOJOListBySql(String sql) {

		return dao.findPOJOListBySql(sql);
	}
	@Override
	public void createPOJOAndAnnex(Object beo, HttpServletRequest request,
			File[] annex, String[] annexFileName, String[] annexContentType) throws FileUploadException {
		String id = dao.save(beo).toString();
		uploadAnnex(request, id, beo.getClass().getSimpleName(), annex, annexFileName, annexContentType);
	}
	@Override
	public void modifyPOJOAndAnnex(Object beo, HttpServletRequest request,
			File[] annex, String[] annexFileName, String[] annexContentType, String id) throws FileUploadException, SQLException {
		dao.update(beo);
		if (annex != null) {
			deleteAnnex(beo, id);
			uploadAnnex(request, id, beo.getClass().getSimpleName(), annex, annexFileName, annexContentType);
		}
	}
	public void uploadAnnex(HttpServletRequest request, String id, String tableName, File[] annex, String[] annexFileName,
			String[] annexContentType) throws FileUploadException {
		String filePath = request.getRealPath(File.separator) + Constants.ANNEX_DIR + File.separator + 
			Utils.getCurrentDateString("yyyyMMdd") + File.separator + tableName;
		if (annex != null) {
			File file = new File(filePath);
			if (!file.exists()) {
				file.mkdirs();
			}
			FileOutputStream out = null;
			FileInputStream in = null;
			byte[] buff = new byte[1024];
			int length = 0;
			int annexNum = annex.length;
			String fileType;
			String []saveName = new String[annexNum];
			for (int i = 0; i < annexNum; i++) {
				if (annexFileName[i] != null && annexFileName[i].indexOf(".") != -1) {
					fileType = annexFileName[i].substring(annexFileName[i]
							.lastIndexOf(".") + 1);
				} else {
					fileType = "";
				}
				saveName[i] = new StringBuffer()
					.append(i)
					.append("_")
					.append(id)
					.append(".")
					.append(fileType).toString();
				try {
					synchronized(saveName[i]) {
						out = new FileOutputStream(filePath + File.separator
								+ saveName[i]);
					}
					if (annex[i].length() > 0) {
						in = new FileInputStream(annex[i]);
						if (in != null) {
							while ((length = in.read(buff)) != -1) {
								out.write(buff, 0, length);
							}
							in.close();
							out.close();
						}
					} else {
						out.close();
					}
					Annex annexCreate = new Annex();
					annexCreate.setAnnexDate(new Date());
					annexCreate.setAnnexName(annexFileName[i]);// 真实的附件名称
					annexCreate.setAnnexSize(annex[i].length() + "");// 附件大小
					annexCreate.setAnnexAlias(saveName[i]);// 服务器上面保存的名称
					annexCreate.setAnnexType(fileType);// 附件类型
					annexCreate.setAnnexPath(filePath + File.separator + saveName[i]);//文件全路径：只能上传500字符的路径
					annexCreate.setTableId(id);
					annexCreate.setTableName(tableName);
					dao.save(annexCreate);
				} catch (Exception e) {
					try {
						if (in != null) {
							in.close();
						}
					} catch (IOException e1) {
						e1.printStackTrace();
					}
					try {
						if (out != null) {
							out.close();
						}
					} catch (IOException e1) {
						e1.printStackTrace();
					}
					for (int j = 0; j < annexNum; j++) {
						Utils.delFile(filePath + File.separator + saveName[j]);
					}
					e.printStackTrace();
					throw new FileUploadException("附件上传失败，请检查网络！");
				}
			}
		}
	}
	@Override
	public void createPOJOAndAnnex(Object beo, HttpServletRequest request,
			String annex, String annexFileName) throws FileUploadException {
		String id = dao.save(beo).toString();
		uploadSimpleFile(request, id, null, beo.getClass().getSimpleName(), annex, annexFileName);
	}
	@Override
	public void modifyPOJOAndAnnex(Object beo, HttpServletRequest request,
			String annex, String annexFileName, String id, String saveName) throws FileUploadException, SQLException {
		String temp = null;
		temp = uploadSimpleFile(request, id, saveName, beo.getClass().getSimpleName(), annex, annexFileName);
		//先这样处理，以后改成反射
		if (beo instanceof BaseUser) {
			((BaseUser) beo).setPhoto(temp);
			dao.update(beo);
		}
		
	}
	public String uploadSimpleFile(HttpServletRequest request, String id, String fileSaveName, String tableName, String annex, String annexFileName) throws FileUploadException {
		
		String filePath = request.getRealPath(File.separator) + Constants.FILE_DIR + File.separator + tableName;
		Utils.delFile(filePath + File.separator + fileSaveName);
		String saveName = null;
		if (!Utils.isStringNull(annex)) {
			File file = new File(filePath);
			if (!file.exists()) {
				file.mkdirs();
			}
			FileOutputStream out = null;
			FileInputStream in = null;
			byte[] buff = new byte[1024];
			int length = 0;
			String fileType;
			if (annex != null && annex.indexOf(".") != -1) {
				fileType = annex.substring(annex
						.lastIndexOf(".") + 1);
			} else {
				fileType = "";
			}
			if (Utils.isStringNull(fileSaveName)) {
				saveName = new StringBuffer()
				.append(id)
				.append(".")
				.append(fileType).toString();
			} else {
				saveName = fileSaveName;
			}
			try {
				synchronized(saveName) {
					out = new FileOutputStream(filePath + File.separator
							+ saveName);
				}
				if (annex.length() > 0) {
					in = new FileInputStream(annex);
					if (in != null) {
						while ((length = in.read(buff)) != -1) {
							out.write(buff, 0, length);
						}
						in.close();
						out.close();
					}
				} else {
					out.close();
				}
				return saveName;
			} catch (Exception e) {
				try {
					if (in != null) {
						in.close();
					}
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				try {
					if (out != null) {
						out.close();
					}
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				Utils.delSimpleFile(filePath + File.separator + saveName);
				e.printStackTrace();
				throw new FileUploadException("附件上传失败，请检查网络！");
			}
		}
		return saveName;
	}
	public void deletePOJOCascadeAnnex(Object beo, String id) throws SQLException {
		dao.delete(beo);
		deleteAnnex(beo, id);
	}
	public void deleteAnnex(Object beo, String id) throws SQLException {
		List annexList = dao.find("from Annex where tableName = '"+beo.getClass().getSimpleName()+"' and tableId = '"+id+"'");
		String[] annexPath = new String[annexList.size()];
		for (int i = 0; i < annexList.size(); i++) {
			Annex annex = (Annex) annexList.get(i);
			annexPath[i] = annex.getAnnexPath();
		}
		dao.delOrUpdate("delete from Annex where table_Name = '"+beo.getClass().getSimpleName()+"' and table_Id = '"+id+"'");
		for (int i = 0; i < annexList.size(); i++) {
			Utils.delFile(annexPath[i]);
		}
	}
}
